package dse.modules.eln;

public class GeometryUtil {
	
	/** This is a utility class, so no instances are allowed. */
	private GeometryUtil () {/**/}
	public static double Radius = 3958.9;
	public static int MidAngle = 180;
	public static int MaxAngle = 360;
	
	public static double distance(double longitude1, double latitude1, 
			double longitude2, double latitude2)
	{
		// Remember we have to wrap around distnaces...
		if(longitude1 == longitude2)
		{
			return distance(latitude1, latitude2);
		}
		else if(latitude1 == latitude2)
		{
			return distance(longitude1, longitude2, latitude1);
		}
		else
		{
			double arcLa1 = AngleToArc(latitude1);
			double arcLa2 = AngleToArc(latitude2);
			double rightDistance = Math.abs(Math.sin(arcLa2)-Math.sin(arcLa1));
			double lineLo1 = Math.cos(arcLa1);
			double lineLo2 = Math.cos(arcLa2);
			double arcLo = AngleToArc(wrap(longitude2 - longitude1));
			double lineDistance = lineLo1*lineLo1 + lineLo2*lineLo2 + rightDistance*rightDistance
									- 2*lineLo1*lineLo2*Math.cos(arcLo);
			double arcGl = Math.acos((2-lineDistance)/2);
			return Radius*arcGl;
		}
	}

	public static double distance (double latitude1, double latitude2) 
	{
		return Radius*AngleToArc(wrap(latitude1 - latitude2));
	}
	
	public static double distance(double longitude1, double longitude2, double latitude)
	{
		double arcLa = AngleToArc(Math.abs(latitude));
		double arcLo = AngleToArc(wrap(longitude2-longitude1));
		double radiusLa = Math.cos(arcLa);
		double lineDistance = 2*radiusLa*radiusLa*(1 - Math.cos(arcLo));
		double arcGl = Math.acos((2-lineDistance)/2);
		return Radius*arcGl;		
	}

	public static double wrap (double angle) 
	{
		angle = Math.abs(angle);
		if (angle <= MidAngle)
		{
			return angle;
		}
		else
		{
			return MaxAngle - angle;
		}
	}
	
	public static double AngleToArc(double angle)
	{
		return angle*Math.PI/MidAngle;
	}
}
